package com.print;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterName;

import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.impl.datamatrix.DataMatrixBean;
import org.krysalis.barcode4j.impl.datamatrix.SymbolShapeHint;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class LableExcel {

	private static final int resolution;

	private double width;
	private double height;
	private int dpi;
	
	private BufferedImage bi;
	private Graphics2D graphics;

	static {
		resolution = Toolkit.getDefaultToolkit().getScreenResolution();
	}

	public double getWidth() {
		return width;
	}

	public void setWidth(double width) {
		this.width = width;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public int getDpi() {
		return dpi;
	}

	public void setDpi(int dpi) {
		this.dpi = dpi;
	}

	/**
	 * 初始化标签
	 * 
	 * @param width
	 * @param height
	 */
	private void init(double width, double height,int dpi) {
		int w = (int)width;
		int h = (int)height;
		bi = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
		graphics = bi.createGraphics();
		graphics.setColor(Color.WHITE);
		graphics.fillRect(0, 0, w, h);
		graphics.setColor(Color.BLACK);
	}

	public LableExcel(double width, double height,int dpi) {
		this.width = width;
		this.height = height;
		this.dpi = dpi;
		init(this.width, this.height, this.dpi);
	}

	/**
	 * 添加标签文本
	 * 
	 * @param text
	 * @return
	 */
	public LableExcel addText(Text text) {
		int x = UnitConv.mm2px(text.getX(), dpi);
		int y = UnitConv.mm2px(text.getY(), dpi);
		double n = dpi / resolution;
		int fontSize = (int) Math.round(text.getFontSize() * n);
		Font font = new Font(text.getFontName(), text.getFontStyle(), fontSize);
		graphics.setFont(font);
		graphics.drawString(text.getText(), x, y);
		return this;
	}
	/**
	 * 添加标签线段
	 * 
	 * @param line
	 * @return
	 */
	public LableExcel addLine(Line line) {
		int x = UnitConv.mm2px(line.getX(), dpi);
		int y = UnitConv.mm2px(line.getY(), dpi);
		int length = UnitConv.mm2px(line.getLength(), dpi);
		int lineWidth = UnitConv.mm2px(line.getLineWidth(), dpi) / 2;
		double r = line.getDirection() * Math.PI / 180;
		double s = Math.sin(r);
		double c = Math.cos(r);
		int x11 = (int) (x - lineWidth * s);
		int x12 = (int) (x + lineWidth * s);
		int y11 = (int) (y - lineWidth * c);
		int y12 = (int) (y + lineWidth * c);
		x = (int) (x + length * c);
		y = (int) (y - length * s);
		int x21 = (int) (x + lineWidth * s);
		int x22 = (int) (x - lineWidth * s);
		int y21 = (int) (y + lineWidth * c);
		int y22 = (int) (y - lineWidth * c);
		int[] xPoints = new int[] { x11, x12, x21, x22 };
		int[] yPoints = new int[] { y11, y12, y21, y22 };
		graphics.fillPolygon(xPoints, yPoints, 4);
		return this;
	}

	/**
	 * 添加标签矩形框
	 * 
	 * @param rectangle
	 * @return
	 */
	public LableExcel addRectangle(Rectangle rectangle) {
		int x = UnitConv.mm2px(rectangle.getX(), dpi);
		int y = UnitConv.mm2px(rectangle.getY(), dpi);
		int width = UnitConv.mm2px(rectangle.getWidth(), dpi);
		int height = UnitConv.mm2px(rectangle.getHeight(), dpi);
		int lineWidth = UnitConv.mm2px(rectangle.getLineWidth(), dpi);
		graphics.fillRect(x, y, width, height);
		graphics.setColor(Color.WHITE);
		x += lineWidth;
		y += lineWidth;
		width -= 2 * lineWidth;
		height -= 2 * lineWidth;
		graphics.fillRect(x, y, width, height);
		graphics.setColor(Color.BLACK);
		return this;
	}

	/**
	 * 清除所有标签项
	 * 
	 */
	public void reset() {
		int width = UnitConv.mm2px(this.width, dpi);
		int height = UnitConv.mm2px(this.height, dpi);
		graphics.setColor(Color.WHITE);
		graphics.fillRect(0, 0, width, height);
		graphics.setColor(Color.BLACK);
	}

	/**
	 * 打印标签
	 * 
	 * @throws ImageFormatException
	 * 
	 * @throws IOException
	 * @throws PrintException
	 */
	public void print() throws ImageFormatException, IOException,
			PrintException {
		byte[] byteArray = getBytes();
		PrintService service = PrintServiceLookup.lookupDefaultPrintService();
		DocPrintJob job = service.createPrintJob();
		DocAttributeSet das = new HashDocAttributeSet();
		Doc doc = new SimpleDoc(byteArray, DocFlavor.BYTE_ARRAY.JPEG, das);
		PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
		pras.add(new MediaPrintableArea(0, 0, (float) width, (float) height,
				MediaPrintableArea.MM));
		pras.add(PrintQuality.HIGH);
		job.print(doc, pras);
	}
	
    public void print(String printerName) throws ImageFormatException, IOException, PrintException {
        HashAttributeSet has = new HashAttributeSet();
        has.add(new PrinterName(printerName, null));
        byte[] byteArray = getBytes();
        PrintService[] services = PrintServiceLookup.lookupPrintServices(null, has);
        PrintService service = null;
        if (services == null || services.length == 0) {
            service = PrintServiceLookup.lookupDefaultPrintService();
        } else {
            service = services[0];
        }
        DocPrintJob job = service.createPrintJob();
        DocAttributeSet das = new HashDocAttributeSet();
        Doc doc = new SimpleDoc(byteArray, DocFlavor.BYTE_ARRAY.JPEG, das);
        PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
        pras.add(new MediaPrintableArea(0, 0, (float) width, (float) height, MediaPrintableArea.MM));
        pras.add(PrintQuality.HIGH);
        job.print(doc, pras);
    }
	/**
	 * 销毁标签
	 * 
	 */
	public void dispose() {
		graphics.dispose();
	}

	/**
	 * 获取标签以JPEG编码后的字节码
	 * 
	 * @return
	 * @throws IOException
	 * @throws ImageFormatException
	 */
	public byte[] getBytes() throws ImageFormatException, IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
		param.setQuality(1F, false);
		encoder.encode(bi, param);
		byte[] byteArray = baos.toByteArray();
		baos.close();
		return byteArray;
	}

	/**
	 * 保存以JPEG编码后的图片
	 * 
	 * @param out
	 * @throws IOException
	 * @throws ImageFormatException
	 */
	public void save(OutputStream out) throws ImageFormatException, IOException {
		byte[] byteArray = getBytes();
		out.write(byteArray);
	}

}
